//     Zepto.js
//     (c) 2010-2016 Thomas Fuchs
//     Zepto.js may be freely distributed under the MIT license.
//
//     Some code (c) 2005, 2013 jQuery Foundation, Inc. and other contributors

(function ($) {
  										var slice = Array.prototype.slice;

  										function Deferred(func) {
    										var tuples = [
          // action, add listener, listener list, final state
          ['resolve', 'done', $.Callbacks({ once: 1, memory: 1 }), 'resolved'],
          ['reject', 'fail', $.Callbacks({ once: 1, memory: 1 }), 'rejected'],
          ['notify', 'progress', $.Callbacks({ memory: 1 })]
        										],
        										state = 'pending',
        										promise = {
          										state() {
            										return state;
          },
          										always() {
            										deferred.done(arguments).fail(arguments);
            										return this;
          },
          										then(/* fnDone [, fnFailed [, fnProgress]] */) {
            										var fns = arguments;
            										return Deferred(function (defer) {
              										$.each(tuples, function (i, tuple) {
                										var fn = $.isFunction(fns[i]) && fns[i];
                										deferred[tuple[1]](function () {
                  										var returned = fn && fn.apply(this, arguments);
                  										if (returned && $.isFunction(returned.promise)) {
                    										returned.promise()
                      .done(defer.resolve)
                      .fail(defer.reject)
                      .progress(defer.notify);
                  } else {
                    										var context = this === promise ? defer.promise() : this,
                        										values = fn ? [returned] : arguments;
                    										defer[tuple[0] + 'With'](context, values);
                  }
                });
              });
              										fns = null;
            }).promise();
          },

          										promise(obj) {
            										return obj != null ? $.extend(obj, promise) : promise;
          }
        },
        										deferred = {};

    										$.each(tuples, function (i, tuple) {
      										var list = tuple[2],
          										stateString = tuple[3];

      										promise[tuple[1]] = list.add;

      										if (stateString) {
        										list.add(function () {
          										state = stateString;
        }, tuples[i ^ 1][2].disable, tuples[2][2].lock);
      }

      										deferred[tuple[0]] = function () {
        										deferred[tuple[0] + 'With'](this === deferred ? promise : this, arguments);
        										return this;
      };
      										deferred[tuple[0] + 'With'] = list.fireWith;
    });

    										promise.promise(deferred);
    										if (func) func.call(deferred, deferred);
    										return deferred;
  }

  										$.when = function (sub) {
    										var resolveValues = slice.call(arguments),
        										len = resolveValues.length,
        										i = 0,
        										remain = len !== 1 || (sub && $.isFunction(sub.promise)) ? len : 0,
        										deferred = remain === 1 ? sub : Deferred(),
        										progressValues, progressContexts, resolveContexts,
        										updateFn = function (i, ctx, val) {
          										return function (value) {
            										ctx[i] = this;
            										val[i] = arguments.length > 1 ? slice.call(arguments) : value;
            										if (val === progressValues) {
              										deferred.notifyWith(ctx, val);
            } else if (!(--remain)) {
              										deferred.resolveWith(ctx, val);
            }
          };
        };

    										if (len > 1) {
      										progressValues = new Array(len);
      										progressContexts = new Array(len);
      										resolveContexts = new Array(len);
      										for (; i < len; ++i) {
        										if (resolveValues[i] && $.isFunction(resolveValues[i].promise)) {
          										resolveValues[i].promise()
            .done(updateFn(i, resolveContexts, resolveValues))
            .fail(deferred.reject)
            .progress(updateFn(i, progressContexts, progressValues));
        } else {
          										--remain;
        }
      }
    }
    										if (!remain) deferred.resolveWith(resolveContexts, resolveValues);
    										return deferred.promise();
  };

  										$.Deferred = Deferred;
})(Zepto);
